package de.justphil.tcg.tcgserver.game.mechanics.property;

import java.util.List;

import de.justphil.tcg.tcgserver.game.mechanics.event.Event;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.monster.Monster;
import de.justphil.tcg.tcgserver.game.mechanics.monster.MonsterList;

public abstract class Aura extends Property {

	public Aura(Game game) {

		super(game);
	}

	@Override
	protected MonsterList handleEvent(Event event) {

		MonsterList monsters = new MonsterList();
		
		int eventType = event.getType();

		switch (eventType) {
		case Event.EVENT_MONSTER_PLACED:

			monsters.add(handleMonsterPlaced((Monster) event.getData()));
			return monsters;

		case Event.EVENT_MONSTER_REMOVED:

			monsters.add(handleMonsterRemoved((Monster) event.getData()));
			return monsters;

		default:
			break;
		}
		return null;
	}

	protected abstract int getProvidedProperty();

	@Override
	protected List<Integer> getListeningEventTypes() {

		List<Integer> types = super.getListeningEventTypes();
		types.add(Event.EVENT_MONSTER_PLACED);
		types.add(Event.EVENT_MONSTER_REMOVED);

		return types;
	}

	@Override
	protected MonsterList handleActivation() {

		MonsterList allies = getBoardInfo().getAllies(getMonster());
		for (Monster ally : allies) {

			providePropertyOnce(ally, getProvidedProperty());
		}
		return allies;
	}

	@Override
	protected MonsterList handleDeactivation() {

		return withdrawAllProperties();
	}

	private Monster handleMonsterPlaced(Monster monster) {

		MonsterList allies = getBoardInfo().getAllies(getMonster());

		if (monster != getMonster() && allies.contains(monster)) {

			providePropertyOnce(monster, getProvidedProperty());
			return monster;
		}
		return null;
	}

	private Monster handleMonsterRemoved(Monster monster) {

		if (monster != getMonster()) {

			withdrawProperties(monster);
			return monster;
		}
		return null;
	}
}
